home *** CD-ROM | disk | FTP | other *** search
/ Amiga CD-Sensation: Golden Games / Amiga CD-Sensation - Ausgabe 2 - Golden Games (1996)(GTI - Schatztruhe)(DE)[!].iso / Brain Activity / UChess / Source / search.c < prev    next >
C/C++ Source or Header  |  1994-08-04  |  55KB  |  1,971 lines

  1. // about splitting the search into a new thread, perhaps
  2. // the best place to check the msg queue is in UpdateClocks,
  3. // called from ElapsedTime, you would set a flag in here
  4. // before you call each ElapsedTime, telling the system
  5. // to check the msg queue in there for any new moves
  6.  
  7. //char strx[40];
  8. #define CLEARHISTBETWEENMOVES // old way to handle hist table
  9. /*
  10.  * search.c - C source for GNU CHESS
  11.  *
  12.  * Copyright (c) 1988,1989,1990 John Stanback Copyright (c) 1992 Free Software
  13.  * Foundation
  14.  *
  15.  * This file is part of GNU CHESS.
  16.  *
  17.  * GNU Chess is free software; you can redistribute it and/or modify it under
  18.  * the terms of the GNU General Public License as published by the Free
  19.  * Software Foundation; either version 2, or (at your option) any later
  20.  * version.
  21.  *
  22.  * GNU Chess is distributed in the hope that it will be useful, but WITHOUT ANY
  23.  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  24.  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  25.  * details.
  26.  *
  27.  * You should have received a copy of the GNU General Public License along with
  28.  * GNU Chess; see the file COPYING.  If not, write to the Free Software
  29.  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  30.  */
  31. #include "gnuchess.h"
  32.  
  33. #define PTRHEIGHT 55
  34. extern UWORD chip myPointer[];
  35. #include <proto/intuition.h>
  36. extern struct Window __aligned *wG;
  37. extern int __aligned SupervisorMode;
  38.  
  39.  
  40. #define ZEROALLBETWEENPLY 1
  41.  
  42. #ifdef QUIETBACKGROUND
  43. short __aligned background = 0;
  44.  
  45. #endif /* QUIETBACKGROUND */
  46. static short int __aligned DepthBeyond;
  47. short __aligned Threat[MAXDEPTH];
  48. unsigned short int __aligned PrVar[MAXDEPTH];
  49. extern short int ISZERO;
  50. extern long EADD,EGET;
  51. extern char mvstr[8][8];
  52. extern short int recycle;
  53. extern int __aligned GetEntryDone;
  54. extern int trying_again;
  55. short int __aligned myflagdeepnull=0xff;
  56. int got_20000=0;
  57. short __aligned ThreatSave[MAXDEPTH]; /* tom@izf.tno.nl */
  58. extern short __aligned QueenCheck[MAXDEPTH]; /* tom@izf.tno.nl */
  59. #if defined NULLMOVE || defined DEEPNULL
  60. short int __aligned no_null;
  61. short int __aligned null;         /* Null-move already made or not */
  62. short int __aligned PVari;        /* Is this the PV */
  63. #endif
  64. #ifdef DEBUG40
  65. extern int whichway;
  66. #endif
  67. #ifdef DEBUG
  68. unsigned short __aligned DBLINE[MAXDEPTH];
  69. struct leaf __aligned *dbptr;
  70.  
  71. #endif
  72. short __aligned start_stage;
  73. short __aligned thrashing_tt; /* must we recycle slots at random. TomV */
  74. short int __aligned zwndw;
  75.  
  76. #include "ataks3.h"
  77.  
  78. #define __USE_SYSBASE
  79. #include <proto/exec.h>
  80.  
  81. extern long OrigResponse;
  82. extern int global_tmp_score;
  83. extern int previous_score;
  84. short __aligned myflagpvs=true;
  85. int __aligned backsrchaborted=0;
  86. int __aligned Sdepth2=0;
  87. extern int MoveNowOK;
  88. extern int procpri;
  89. extern struct Process *myproc;
  90. extern struct MsgPort *InThreadPort;
  91. extern struct myMsgStruct Global_Message;
  92.  
  93. int __aligned RealThink=0;
  94.  
  95. #ifdef SPEED_PRECALC
  96. unsigned short __aligned PreCalcedHint;
  97. unsigned short __aligned PreCalcedMove;
  98. int DoPreCalc (unsigned INTSIZE *, INTSIZE);
  99. #endif
  100. int __aligned Castled[2]={0,0};
  101. int __aligned myEnPassant[2]={0,0};
  102.  
  103. #include "ttable.c"
  104.  
  105.  
  106. short int __inline repetition (void);
  107.  
  108.  
  109. #include "debug41.h"
  110. /* ............    MOVE GENERATION & SEARCH ROUTINES    .............. */
  111.  
  112. //#define STRAIGHT4PL70 1 // for repetiton code
  113. #ifndef STRAIGHT4PL70
  114. // improved Kong Sian Repetition
  115.  
  116. short int __inline
  117. repetition ()
  118.  
  119. /*  Check for draw by threefold repetition.  */
  120.  
  121. {
  122.   register short i, cnt;
  123.  
  124.   cnt = 0;
  125.   /* try to avoid work */
  126.   if (GameCnt > Game50 + 3)
  127.     for (i = GameCnt; i >= Game50; i--)
  128.       if (hashbd == GameList[i].hashbd && hashkey == GameList[i].hashkey)
  129.         cnt++;
  130.  
  131.   return cnt;
  132. }
  133.  
  134. #else // straight 4pl70 repetition
  135. short int __inline
  136. repetition ()
  137.  
  138. /*  Check for draw by threefold repetition.  */
  139.  
  140. {
  141.   register SHORT i, c, cnt;
  142.   register SHORT m;
  143.   SHORT b[64];
  144.  
  145.   cnt = c = 0;
  146.   /* try to avoid work */
  147.   if (GameCnt > Game50 + 3)
  148.     {
  149.       ClearMem(b,sizeof(b));
  150.       for (i = GameCnt; i >= Game50; i--)
  151.     {
  152.       m = GameList[i].gmove;
  153.       /* does piece exist on diff board? */
  154.       if (b[m & 0x3f])
  155.         {
  156.           /* does diffs cancel out, piece back? */
  157.           if ((b[m >> 8] += b[m & 0x3f]) == 0)
  158.         --c;
  159.           b[m & 0x3f] = 0;
  160.         }
  161.       else
  162.         {
  163.           /* create diff */
  164.           ++c;
  165.           /* does diff cancel out another diff? */
  166.           if (!(b[m >> 8] -= (b[m & 0x3f] = board[m & 0x3f] +
  167.                   (color[m & 0x3f] << 8))))
  168.         --c;
  169.         }
  170.       /* if diff count is 0 we have a repetition */
  171.       if (c == 0)
  172.         if ((i ^ GameCnt) & 1)
  173.           cnt++;
  174.     }
  175.     }
  176.   return cnt;
  177. }
  178.  
  179. #endif // striaght 4pl70 repetition
  180.  
  181. int plyscore, globalscore;
  182. int
  183. pick (short int p1, short int p2)
  184.  
  185. /*
  186.  * Find the best move in the tree between indexes p1 and p2. Swap the best
  187.  * move into the p1 element.
  188.  *
  189.  */
  190. {
  191.   register struct leaf *p, *q, *r, *k;
  192.   register s0;
  193.   struct leaf temp;
  194.  
  195.   k = p = &Tree[p1];
  196.   q = &Tree[p2];
  197.   s0 = p->score;
  198.   for (r = p + 1; r <= q; r++)
  199.     if (r->score != 9999 && (r->score) > s0) // this is the PL70 way!
  200. //    if ((r->score) > s0) 
  201.       {
  202.     s0 = (r->score);
  203.     p = r;
  204.       }
  205.   if (p != k)
  206.     {
  207.       temp = *p;
  208.       *p = *k;
  209.       *k = temp;
  210.       return true;
  211.     }
  212.   return false;
  213. }
  214.  
  215. #ifdef DEBUG
  216. unsigned short trace[MAXDEPTH];
  217. char traceline[256];
  218. unsigned short tracelog[MAXDEPTH];
  219. int tracen = 0;
  220. int traceflag = 0;
  221. int traceply = 0;
  222. #endif
  223. int __aligned bookflag = false;
  224. int __aligned Jscore = 0;
  225.  
  226. static int __aligned TCcount, TCleft;
  227. void
  228. SelectMove (short int side, short int iop)
  229. /*
  230.  * Select a move by calling function search() at progressively deeper ply
  231.  * until time is up or a mate or draw is reached. An alpha-beta window of
  232.  * -Awindow to +Bwindow points is set around the score returned from the
  233.  * previous iteration. If Sdepth != 0 then the program has correctly
  234.  * predicted the opponents move and the search will start at a depth of
  235.  * Sdepth+1 rather than a depth of 1.
  236.  */
  237. {
  238.   static short int i, tempb, tempc, tempsf, tempst, xside, rpt;
  239.   static short int alpha, beta, score;
  240.   static struct GameRec *g;
  241.   int earlyflag;
  242.  
  243. #ifndef CLEARHISTBETWEENMOVES // old way to handle hist table
  244.   int cnt;
  245.   ULONG *tmphistptr;
  246. #endif
  247.  
  248.   char mystr[32];
  249.   short InChkDummy;
  250.   short start_score;
  251. #ifdef DEBUG
  252.  
  253. if(debuglevel & (512|1024)){
  254.     char b[32];
  255.     short c1,c2,r1,r2;
  256. tracen=0;
  257. traceflag = false;
  258. traceply = 0;
  259. tracelog[0]=0;
  260. while(true){
  261.     /*printf("debug?");
  262.     gets(b);*/
  263.     if(b[0] == 'p')traceply = atoi(&b[1]);
  264.     else
  265.     if(b[0] == '\0')break;
  266.     else{
  267.         c1 = b[0] - 'a';
  268.               r1 = b[1] - '1';
  269.               c2 = b[2] - 'a';
  270.               r2 = b[3] - '1';
  271.               trace[++tracen] = (locn (r1, c1) << 8) | locn (r2, c2);
  272.     }
  273.     if(tracen == 0 && traceply >0)traceflag = true;
  274.     }
  275.     
  276. }
  277. #endif
  278.  
  279. //  InitializeStats(); // MY FIX FOR UNDO PROBLEMS!!! TMP!!!
  280.  
  281. if (!SupervisorMode)
  282.  SetPointer(wG,myPointer,PTRHEIGHT,0x10L,0L,0L);
  283. got_20000 = 0;
  284. if (iop != 2)
  285.  {
  286.   RealThink = 1;
  287.   if (!GetEntryDone)
  288.    {
  289.     Global_Message.myData = 1L;
  290.     Forbid();
  291.     PutMsg(InThreadPort,(struct Message *)&Global_Message);
  292.     Permit();
  293.     GetEntryDone = 1;
  294.    }
  295.  }
  296. else
  297.  RealThink = 0;
  298. start_again:
  299.   flag.timeout = false;
  300.   flag.back = flag.musttimeout = false;
  301.   INCscore = 0; // new from 4pl70, do I want this?
  302.   xside = side ^ 1;
  303.   recycle = (GameCnt % rehash) - rehash;
  304.   /* if background mode set to infinite */
  305.   if (iop == 2)
  306.     {
  307.       Sdepth2 = 0;
  308.       (void)SetTaskPri((struct Task *)myproc,0);
  309.       OrigResponse = ResponseTime = 9999999;
  310. #ifdef QUIETBACKGROUND
  311.       background = true;
  312. #endif /* QUIETBACKGROUND */
  313.     }
  314.   else
  315.     {
  316.       player = side;
  317.       if (TCflag)
  318.     {
  319.       TCcount = 0;
  320. #ifdef QUIETBACKGROUND
  321.       background = false;
  322. #endif /* QUIETBACKGROUND */
  323.       if (TimeControl.moves[side] < 1)
  324.         TimeControl.moves[side] = 1;
  325.       /* special case time per move specified */
  326.       if (flag.onemove)
  327.         {
  328.           OrigResponse = ResponseTime = TimeControl.clock[side] - 100;
  329.           TCleft = 0;
  330.         }
  331.       else
  332.         {
  333.           /* calculate avg time per move remaining */
  334.           TimeControl.clock[side] += TCadd;
  335.  
  336.           ResponseTime = (TimeControl.clock[side]) / (((TimeControl.moves[side]) * 2) + 1);
  337.           TCleft = (int)ResponseTime / 3;
  338.           ResponseTime += TCadd/2;
  339.           if (TimeControl.moves[side] < 5)
  340.         TCcount = MAXTCCOUNTX - 1;
  341.         }
  342.       if (ResponseTime < 101)
  343.         {
  344.           ResponseTime = 100;
  345.           TCcount = MAXTCCOUNTX;
  346.         }
  347.       else if (ResponseTime < 200)
  348.         {
  349.           TCcount = MAXTCCOUNTX - 1;
  350.         }
  351.           OrigResponse = ResponseTime;
  352.           if ((TimeControl.moves[side] > 9))
  353.            ResponseTime += 51;
  354. //           ResponseTime = ResponseTime + (ResponseTime/4); // ADDED TO 2.50 to make clock better
  355.     }
  356.       else
  357.        {
  358. #ifdef QUIETBACKGROUND
  359.       background = false;
  360. #endif /* QUIETBACKGROUND */
  361.     OrigResponse = ResponseTime = MaxResponseTime;
  362.        }
  363.       if (TCleft)
  364.     {
  365.       TCcount = ((int)((TimeControl.clock[side] - ResponseTime)) / 2) / TCleft;
  366.       if (TCcount > MAXTCCOUNTX)
  367.         TCcount = 0;
  368.       else
  369.         TCcount = MAXTCCOUNTX - TCcount;
  370.     }
  371.       else
  372.     TCcount = MAXTCCOUNTX;
  373.     }
  374.   if (MoveNowOK)
  375.    {
  376.     thinking2 = 1; /* allow move now menu item to work */
  377.    }
  378.   else
  379.    {
  380.     thinking2 = 0; /* do not allow move now menu item to work */
  381.    }
  382. #ifndef OLD_LOOKAHEAD // this is faster for predicted moves
  383.   if (Sdepth > 0) // guessed correct move!
  384.    {
  385.      if (TCflag)
  386.        time0 = time(0L);
  387. #ifdef QUIETBACKGROUND
  388.     if (!background)
  389. #endif /* QUIETBACKGROUND */
  390.      SearchStartStuff (side);
  391.     trying_again = 0;
  392.     if ((GameCnt>2)&&(TCflag)&&(global_tmp_score >= (previous_score-50))&&(Sdepth >= GlobalTgtDepth)
  393.           &&(global_tmp_score >= (GameList[GameCnt-1].score - 50)))
  394.      {
  395.       if (Sdepth >= (GameList[GameCnt-1].depth))
  396.        flag.timeout = true;
  397.       goto ForceTheMove2;
  398.      }
  399.     if ((TCflag)||(backsrchaborted))
  400.      {
  401.       goto ForceTheMove2; // for now use 2, it was ForceTheMove before
  402.      }
  403.     else
  404.      {
  405.       goto ForceTheMove2;
  406.      }
  407.    }
  408. #endif
  409.   ExtraTime = 0;
  410.   ExaminePosition ();
  411. //  score = ScorePosition (side);
  412.   stage= -1; /* Force init in UpdateWeights() */
  413.   start_score= Tscore[0]= Tscore[1]= score=
  414.     evaluate (side, 1, 1, 0, -9999, 9999, 0, &InChkDummy);
  415.   start_stage= stage;
  416. #ifdef QUIETBACKGROUND
  417.   if (!background)
  418. #endif /* QUIETBACKGROUND */
  419.     ShowSidetoMove ();
  420. #ifdef notdef
  421.   if (TCflag && TCcount < MAXTCCOUNT)
  422.     if (score < SCORETIME)
  423.       {
  424.     ExtraTime += TCleft;
  425.     TCcount++;
  426.       }
  427. #endif
  428.  
  429. #ifdef QUIETBACKGROUND
  430.   if (!background)
  431. #endif /* QUIETBACKGROUND */
  432.     SearchStartStuff (side);
  433.  
  434. #ifdef HISTORY
  435. #ifndef CLEARHISTBETWEENMOVES
  436. // keep hist info between moves, just shift it all over one bit (depth)
  437. tmphistptr = (ULONG *)history;
  438. for(cnt=0;cnt<(32768/4);cnt++)
  439.  {
  440.   tmphistptr[cnt] = ((tmphistptr[cnt] >> 1) & 0x7f7f7f7f);
  441.  }
  442. #else // clear history between moves
  443.   ClearMem(history,sizeof (history));
  444. #endif // clear history between moves
  445. #endif // HISTORY
  446.  
  447.   FROMsquare = TOsquare = -1;
  448.   PV = 0;
  449.   if (iop == 1)
  450.     hint = 0;
  451. #ifndef AMIGA
  452.   for (i = 0; i < MAXDEPTH; i++)
  453.    {
  454.     PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
  455.    }
  456. #else
  457.   ClearMem(PrVar,MAXDEPTH*sizeof(PrVar[0]));
  458.   ClearMem(killr0,MAXDEPTH*sizeof(killr0[0]));
  459.   ClearMem(killr1,MAXDEPTH*sizeof(killr1[0]));
  460.   ClearMem(killr2,MAXDEPTH*sizeof(killr2[0]));
  461.   ClearMem(killr3,MAXDEPTH*sizeof(killr3[0]));
  462. #endif
  463.   /* set initial window for search */
  464.   alpha = score - ((computer == black) ? BAwindow : WAwindow);
  465.   beta = score + ((computer == black) ? BBwindow : WBwindow);
  466.   rpt = 0;
  467.   TrPnt[1] = 0;
  468.   root = &Tree[0];
  469.   MoveList (side, 1);
  470. #ifdef BEFORE4PL70
  471. if(TrPnt[2]-TrPnt[1] == 0){
  472.     /* if no moves and not in check then draw */
  473.   if (!(SqAtakd3 (PieceList[side][0], xside)))
  474.     {
  475.       root->flags |= draw;
  476.       DRAW = CP[87];            /* No moves */
  477.     } else {
  478. #if !defined CLIENT
  479.     flag.quit = 
  480. #endif
  481.     flag.mate = true;
  482.     root->score = -9999;
  483.     }
  484.     if(iop !=2){
  485.     OutputMove(mystr);
  486.     }
  487.     RealThink = 0;
  488.     ClearPointer(wG);
  489.     return;
  490.     }
  491. #endif // before 4pl70
  492.   for (i = TrPnt[1]; i < TrPnt[2]; i++) pick (i, TrPnt[2] - 1);
  493.   /* can I get a book move? */
  494.   if ((flag.regularstart && Book))
  495.     {
  496.       flag.timeout = bookflag = OpeningBook (&hint, side);
  497.       if (TCflag)
  498.        {
  499.     ResponseTime += ResponseTime;
  500.         OrigResponse = ResponseTime;
  501.        }
  502.     }
  503. #ifdef SPEED_PRECALC
  504.   if ((!flag.timeout)&&(ThinkAheadWorked))
  505.    {
  506.     flag.timeout = DoPreCalc(&hint,side);
  507.    }
  508. #endif
  509.   /* zero stats for hash table */
  510. #ifdef ZEROALLBETWEENPLY
  511. #ifdef OLDTTABLE
  512.   if (!bookflag)
  513.    {
  514.     ZeroTTable();
  515.     EADD = EGET = 0;
  516.    }
  517. #endif
  518. #endif
  519.   reminus = replus = 0;
  520.   GenCnt = NodeCnt = ETnodes = EvalNodes = HashCnt = FHashAdd = HashAdd = FHashCnt = THashCol = HashCol = 0;
  521.   globalscore = plyscore = score;
  522.   zwndw = 20;
  523.   Jscore = trying_again = global_tmp_score = previous_score = 0;
  524. #include "debug4.h"
  525.   /********************* main loop ********************************/
  526.     Sdepth = (MaxSearchDepth<(MINDEPTH-1))?MaxSearchDepth:(MINDEPTH-1);
  527. /*printf("\n\n");*/
  528. ForceTheMove:
  529.   while (!flag.timeout)
  530.     {
  531. /*printf("time0 = %d et = %d SDepth = %d GameCnt = %d\n",time0, et,Sdepth,GameCnt);*/
  532. /*printf("ThinkAheadWorked = %d  ThinkAheadDepth = %d\n",ThinkAheadWorked,ThinkAheadDepth);*/
  533.       /* go down a level at a time */
  534.       Sdepth++;
  535. #if defined NULLMOVE || defined DEEPNULL
  536.       null = 0;
  537.       PVari = 1;
  538. #endif
  539. //      DepthBeyond = Sdepth + ((Sdepth == 1) ? 7 : 11);
  540.       DepthBeyond = Sdepth +
  541.         ((Sdepth == 1) ? FBEYOND : flag.threat ? SBEYOND: TBEYOND);
  542.       no_null= (emtl[xside] == 0 || emtl[side] == 0);
  543.  
  544. #if !defined CHESSTOOL && !defined XBOARD
  545. #ifdef QUIETBACKGROUND
  546.       if (!background)
  547. #endif /* QUIETBACKGROUND */
  548.     ShowDepth (' ');
  549. #endif
  550.       root->score= Tscore[0]= Tscore[1]= start_score;
  551.       /* search at this level returns score of PV */
  552. //      score = search (side, 1, Sdepth, alpha, beta, PrVar, &rpt, QBLOCK);
  553.       score = search (side, 1, Sdepth, 0, alpha, beta, PrVar, &rpt, QBLOCK, false);
  554.       /* save PV as killer */
  555.       for (i = 1; i <= Sdepth; i++)
  556.     killr0[i] = PrVar[i];
  557.  
  558.       /* low search failure re-search with (-inf,score) limits  */
  559.       if (score < alpha)
  560.     {
  561. #if !defined CHESSTOOL && !defined XBOARD
  562.       reminus++;
  563. #ifdef QUIETBACKGROUND
  564.       if (!background)
  565. #endif /* QUIETBACKGROUND */
  566.         ShowDepth ('-');
  567. #endif
  568.       if (TCflag && TCcount < MAXTCCOUNTR)
  569.         {
  570.           TCcount = MAXTCCOUNTR - 1;
  571.           ExtraTime += (8 * TCleft);
  572.         }
  573. // root->score commented out on 4pl71 FIX!!!
  574.           /*root->score= */Tscore[0]= Tscore[1]= start_score;
  575.       score = search (side, 1, Sdepth, 0, -9999, 9999, PrVar, &rpt,QBLOCK,false);
  576.     }
  577.       /* high search failure re-search with (score, +inf) limits */
  578.       else if (score > beta && !(root->flags & exact))
  579.     {
  580. #if !defined CHESSTOOL && !defined XBOARD
  581.       replus++;
  582. #ifdef QUIETBACKGROUND
  583.       if (!background)
  584. #endif /* QUIETBACKGROUND */
  585.         ShowDepth ('+');
  586. #endif
  587. // root->score commented out on 4pl71 fix
  588.           /*root->score=*/ Tscore[0]= Tscore[1]= start_score;
  589.       score = search (side, 1, Sdepth, 0, -9999, 9999, PrVar, &rpt,QBLOCK,false);
  590.     }
  591.       /**************** out of search ********************************************/
  592. ForceTheMove2:
  593.       if ((flag.timeout)||(flag.musttimeout)||(flag.back))
  594.        earlyflag = true;
  595.       else
  596.        earlyflag = false;
  597.       if (flag.musttimeout || Sdepth >= MaxSearchDepth)
  598.        {
  599.     flag.timeout = true;
  600.        }
  601.       else if (TCflag && (Sdepth > (MINDEPTH - 1)) && (TCcount < MAXTCCOUNTR))
  602.     {
  603.       if (killr0[1] != PrVar[1] /* || Killr0[2] != PrVar[2] */ )
  604.         {
  605.           TCcount++;
  606.           ExtraTime += TCleft;
  607.         }
  608.       if ((abs (score - globalscore) / Sdepth) > ZDELTA)
  609.         {
  610.           TCcount++;
  611.           ExtraTime += TCleft;
  612.         }
  613.     }
  614.       if (score > (Jscore - zwndw) && score > (Tree[1].score + 250)) ExtraTime = 0;
  615. /*printf("sdepth = %d mindepth = %d TCflag = %d \n4*et = %d respt = %d extra = %d\n",Sdepth,MINDEPTH,TCflag,4*et,ResponseTime,ExtraTime);*/
  616. // || rpt > 1 added with 4pl71
  617.       if (root->flags & exact || rpt > 1) flag.timeout = true;
  618.       /*else if (Tree[1].score < -9000) flag.timeout = true;*/
  619.       else if (!(Sdepth < MINDEPTH) && TCflag && ((4 * et) > (2*ResponseTime + ExtraTime))) flag.timeout = true;
  620.       /************************ time control ***********************************/
  621.  
  622.       /* save PV as killer */
  623.       for (i = 1; i <= Sdepth + 1; i++) killr0[i] = PrVar[i];
  624.       if (!flag.timeout) start_score = Tscore[0] = score;
  625.       /* if (!flag.timeout) */
  626. //      for (i = TrPnt[1]+1; i < TrPnt[2]; i++) if (!pick (i, TrPnt[2] - 1)) break;
  627.       /* if done or nothing good to look at quit */
  628.       if ((root->flags & exact) || (score < -9000)) flag.timeout = true;
  629.       /* find the next best move put below root */
  630. #include "debug13.h"
  631.       if (!flag.timeout)
  632.     {
  633.       /* */
  634. #if !defined NODYNALPHA
  635.       Jscore = (plyscore + score) >> 1;
  636. #endif
  637.       zwndw = 20 + abs (Jscore / 12);
  638.       plyscore = score;
  639.       /* recompute search window */
  640.       beta = score + ((computer == black) ? BBwindow : WBwindow);
  641. #if !defined NODYNALPHA
  642.       alpha = ((Jscore < score) ? Jscore : score) - ((computer == black) ? BAwindow : WAwindow) - zwndw;
  643. #else
  644.       alpha = score - ((computer == black) ? BAwindow : WAwindow);
  645. #endif
  646.     }
  647. #if !defined CHESSTOOL && !defined XBOARD
  648. #ifdef QUIETBACKGROUND
  649.       if (!background)
  650. #endif /* QUIETBACKGROUND */
  651.     ShowResults (score, PrVar, '.');
  652. #ifdef DEBUG41
  653.       debug41 (score, PrVar, '.');
  654. #endif
  655. #endif
  656. #include "debug16.h"
  657. #ifdef CHECKMOVERESULTS
  658.       if ((score >= 11000)&&(!got_20000))
  659.        {
  660.         got_20000 = 1;
  661.         Sdepth = 0;
  662.         goto start_again;
  663.        }
  664.       if (((flag.timeout)&&((!PrVar[1])||(!PrVar[2]))&&(!(root->flags & exact))&&(iop != 2)&&(abs(score) < 9000)&&(abs(score)>25))) /* do not trust this move! */
  665.        {
  666.         if ((Sdepth > 2))
  667.          {
  668.           if ((earlyflag))
  669.            {
  670.             Sdepth--;
  671.            }
  672.           if (!trying_again)
  673.            { /* this is first bogus move we have seen */
  674.             ResponseTime = ResponseTime << 1;
  675.             ExtraTime += 251;
  676.            }
  677.           else
  678.            { /* this is not 1st bogus move we have seen */
  679.             ExtraTime += 201;
  680.            }
  681.           trying_again = 1;
  682.           flag.timeout = false;
  683.           flag.back = false;
  684.           flag.musttimeout = false;
  685.          }
  686.        }
  687.       else if (trying_again) /* this move is trustworthy, to an extent */
  688.        {
  689.         if ((TCflag && ((4 * et) > (ResponseTime + ExtraTime - 251)))||(root->flags & exact)) 
  690.          flag.timeout = true;
  691.        }
  692. #endif
  693.       previous_score = score;
  694.     } /* while !flag.timeout */
  695.   /******************************* end of main loop ***********************************/
  696.   /* background mode */
  697.   if (iop == 2)
  698.    {
  699.     if (bookflag) Sdepth = 0;
  700.     if (!flag.easy)
  701.      {
  702.       Sdepth2 = Sdepth;
  703.       if (Sdepth2 > (GlobalTgtDepth+1))
  704.        Sdepth2--;
  705. #ifdef SPEED_PRECALC
  706.       PreCalcedMove = (Tree[TrPnt[1]].f << 8) | (Tree[TrPnt[1]].t);
  707.       PreCalcedHint = ((PrVar[1]) ? PrVar[2] : 0);
  708. #endif
  709.      }
  710.     RealThink = 0;
  711.     ClearPointer(wG);
  712.     return;
  713.    }
  714. #include "debug4.h"
  715. #ifdef PRE4PL70
  716.   if (rpt >= 2)
  717.     {
  718.       root->flags |= draw;
  719.       DRAW = CP[101];        /* Repetition */
  720.     }
  721.   else
  722.     /* if no moves and not in check then draw */
  723. #endif // PRE4pl70
  724.    if ((score == -9999) && !(SqAtakd3 (PieceList[side][0], xside))) // was 9998
  725.     {
  726.       root->flags |= draw;
  727.       DRAW = CP[87];        /* No moves */
  728.     }
  729.   else if (GameCnt == MAXMOVES)
  730.     {
  731.       root->flags |= draw;
  732.       DRAW = CP[80];        /* Max Moves */
  733.     }
  734.   /* not in book so set hint to guessed move for other side */
  735.   if (!bookflag)
  736.    {
  737.     hint = ((PrVar[1]) ? PrVar[2] : 0);
  738.    }
  739.   else if ((!Book)||(!flag.regularstart))
  740.    bookflag = 0;
  741.  
  742.   algbr (root->f, root->t, (short) root->flags);
  743.   /* if not mate or draw make move and output it */
  744.   if (((score != -9999)  && (score != 9998) && (rpt <= 2)) || (root->flags & draw))
  745.     {
  746.       MakeMove (side, &Tree[0], &tempb, &tempc, &tempsf, &tempst, &INCscore);
  747. #if !defined NOMATERIAL
  748.       if (flag.material && !pmtl[black] && !pmtl[white] && (mtl[white] < (valueR + valueK)) && (mtl[black] < (valueR + valueK)))
  749.     {
  750.       root->flags |= draw;
  751.       DRAW = CP[224];    /* No pieces */
  752.     }
  753.       else
  754. #endif
  755.       if (!PieceCnt[black] && !PieceCnt[white])
  756.     {
  757.       root->flags |= draw;
  758.       DRAW = CP[88];    /* No pieces */
  759.     }
  760.     }
  761.   else
  762.     { root->score = score;    /* When mate, ignore distinctions! * --SMC */
  763.     }
  764.  
  765.   g = &GameList[GameCnt];
  766.   if (g->flags & capture && g->piece == king)
  767.     {
  768.       flag.mate = flag.illegal = true;
  769.     }
  770.   /* If Time Control get the elapsed time */
  771.   if (TCflag)
  772.     ElapsedTime (1);
  773.   /* if mate set flag */
  774. // this line added from 4pl71 code!
  775.    if (rpt > 1) root->flags |= (draw | exact);
  776.  
  777.    if (score == -9999 || rpt > 1)
  778.      mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = mvstr[4][0] = '\0';
  779.     /* if mate set flag */
  780.   if ((score == -9999) || (score == 9998)) {flag.mate = true; 
  781. #ifndef CLIENT
  782. #ifndef AMIGA
  783.     flag.quit = true;
  784. #endif
  785. #endif
  786.     }
  787.   OutputMove (mystr);
  788.   /* if mate clear hint */
  789.   if (flag.mate)
  790.     hint = 0;
  791.   /* if pawn move or capture or castle or promote zero repitition array */
  792.   if ((board[root->t] == pawn) || (root->flags & (capture | cstlmask | promote)))
  793.     {
  794.       Game50 = GameCnt;
  795.       ZeroRPT ();
  796.     }
  797.   /* add move to game list */
  798.   g->score = score;
  799.   g->nodes = NodeCnt;
  800.   g->time = (et +50)/100;
  801.   g->depth = Sdepth;
  802. #include "debug40.h"
  803.   /* update time comtrol info */
  804.   if (TCflag)
  805.     {
  806. #if defined CHESSTOOL || defined XBOARD
  807.       TimeControl.clock[side] -= (et + OperatorTime + 45);
  808.       timecomp[compptr] = (et + OperatorTime + 45);
  809. #else
  810.       TimeControl.clock[side] -= (et + OperatorTime);
  811.       timecomp[compptr] = (et + OperatorTime);
  812. #endif
  813.       /* finished our required moves - setup the next set */
  814.       --TimeControl.moves[side];
  815.     }
  816.   /* check for end conditions */
  817.   if ((root->flags & draw) /* && flag.bothsides */ )
  818. #if !defined CLIENT
  819.      flag.mate = true;
  820. #else 
  821.     ;
  822. #endif
  823.   else if (GameCnt == MAXMOVES)
  824.     {
  825.       flag.mate = true;
  826.     }
  827.   /* out of move store, you loose */
  828.   else
  829.     /* switch to other side */
  830.     player = xside;
  831.   Sdepth = 0;
  832.   RealThink = 0;
  833.   ClearPointer(wG);
  834. }
  835.  
  836. int
  837. search (short int side,
  838.     register short int ply,
  839.     register short int depth,
  840.     short ext,
  841.     short int alpha,
  842.     short int beta,
  843.     short unsigned int *bstline,
  844.     short int *rpt,
  845.         short SAVEHT,
  846.     int didnull)
  847.  
  848. /*
  849.  * Perform an alpha-beta search to determine the score for the current board
  850.  * position. If depth <= 0 only capturing moves, pawn promotions and
  851.  * responses to check are generated and searched, otherwise all moves are
  852.  * processed. The search depth is modified for check evasions, certain
  853.  * re-captures and threats. Extensions may continue for up to 11 ply beyond
  854.  * the nominal search depth.
  855.  */
  856.  
  857.  
  858. {
  859.   register short j, pnt;
  860.   short tempb, tempc, tempsf, tempst;
  861.   short xside, pbst, score, rcnt, InChk;
  862.   unsigned short mv, nxtline[MAXDEPTH];
  863.   struct leaf *node, tmp;
  864.   short best = -12000;
  865. #ifdef DOIT_4PL68WAY // this is the 4pl68 way to extend search
  866.   int __aligned max_time;
  867. #endif
  868.   short bestwidth = 0;
  869. #if defined NULLMOVE || defined DEEPNULL
  870.   short int __aligned PVsave;
  871.   short int __aligned PVarisave;
  872.   unsigned short __aligned verydeep=0xffff;
  873. #endif
  874. #ifdef DEBUG
  875.   int xxxtmp;
  876.   int tracetmp;
  877. #endif
  878.   short __aligned extdb= 0;
  879.   short __aligned threat= 0;      /* tom@izf.tno.nl */
  880.   short __aligned threat2= 0;     /* tom@izf.tno.nl */
  881.   short __aligned do_pvs;
  882.  
  883.   NodeCnt++;
  884.   /* look every ZNODE nodes for a timeout */
  885.   if (!null)
  886.    {
  887.   if (NodeCnt > ETnodes )
  888.     {
  889.       ElapsedTime (2);
  890.       if (flag.back)
  891.     {
  892.       flag.back = false;
  893.       flag.timeout = true;
  894.       flag.musttimeout = false;
  895.     }
  896.       else if (TCflag || MaxResponseTime)
  897.     {
  898.       if ((et >= (ResponseTime + ExtraTime)) && Sdepth > MINDEPTH && abs(best) < 10000)
  899.         {            /* try to extend to finish ply */
  900. #define TRYEXTEND 1
  901. #ifdef TRYEXTEND
  902.           if ((TCflag && TCcount < MAXTCCOUNTX)&&(GameCnt > 10))
  903.         {
  904.           flag.musttimeout = true;
  905.           TCcount += 1;
  906.           ExtraTime += TCleft;
  907.         }
  908.           else
  909.         {
  910.           flag.timeout = true;
  911.           flag.musttimeout = false;
  912.         }
  913. #else
  914.           if ((TCflag && TCcount < MAXTCCOUNTX)&&(flag.easy))
  915.         {
  916.           flag.musttimeout = true;
  917.           TCcount += 1;
  918.           ExtraTime += TCleft;
  919.         }
  920.           else
  921.         {
  922.           flag.timeout = true;
  923.           flag.musttimeout = false;
  924.         }
  925. #endif
  926.         }
  927.     }
  928.     }
  929.   else if (!TCflag && flag.musttimeout && Sdepth > MINDEPTH)
  930.     {
  931.       flag.timeout = true;
  932.       flag.musttimeout = false;
  933.     }
  934.    } // !null
  935.   xside = side ^ 1;
  936.   if (ply == 1) INCscore = 0; // TMP!! MY Fix for INCscore not init at ply 1
  937.   /* slk is lone king indicator for either side */
  938.   score = evaluate (side, ply, depth, ext, alpha, beta, INCscore, &InChk);
  939.  
  940.   /*
  941.    * check for possible repitition if so call repitition - rpt is
  942.    * repeat count
  943.    */
  944.   if (ProbeRPThash(side,hashkey))
  945.     {
  946.       *rpt = repetition ();
  947.       if (*rpt == 1) score = -contempt;
  948. // next line changed from *rpt > 2 to *rpt > 1 in 4pl71
  949.       else if (*rpt > 1) {
  950.           bstline[ply] = 0;
  951.           return (-contempt);
  952.         }
  953.     }
  954.   else
  955.     *rpt = 0;
  956.  
  957.   /* score > 9000 its a draw or mate */
  958.   if (score > 9000 /*|| root->flags & draw*/) // was commented out is back in with 4pl70
  959.     {
  960.       bstline[ply] = 0;
  961.       return (score);
  962.     }
  963.   /* Do we need to add depth because of special conditions */
  964.   /* if in check or pawn threat or in capture sequence search deeper */
  965.   /*************************************** depth extensions ***********************************/
  966. #ifdef OLDEXT
  967.   if (depth > 0)
  968.     {
  969.       /* Allow opponent a chance to check again */
  970.       if (InChk)
  971.     depth = (depth < 2) ? 2 : depth;
  972.       else if (PawnThreat[ply - 1] ||
  973.            (flag.rcptr && (score > alpha) &&
  974.       (score < beta) && (ply > 2) && CptrFlag[ply - 1] && CptrFlag[ply - 2]))
  975.     ++depth;
  976.     }
  977.   else
  978.     {
  979.       if (score >= alpha &&
  980.       (InChk || PawnThreat[ply - 1] || (hung[side] > 1 /* && ply == Sdepth + 1*/)))
  981.     depth = 1;
  982.       else if (score <= beta &&
  983.            ((ply < Sdepth + 4) && (ply > 4) &&
  984.  
  985.         ChkFlag[ply - 2] && ChkFlag[ply - 4]))
  986.     {
  987.               depth = 1;
  988.         }
  989.     }
  990. #else
  991.  
  992. #define DOTHREAT    (start_stage < THRSTAGE)
  993. #define DOCHECK     (start_stage < CHECKSTAGE)
  994.  
  995.   Threat[ply]= 0;
  996.   if (depth > 0)
  997.     {
  998.       /* Allow opponent a chance to check again */
  999.       if (InChk) {
  1000. #ifdef DOIT_4PL68WAY // this is the 4pl68 way to extend search
  1001.           if (TCflag)
  1002.            max_time = ((OrigResponse<<2) + ExtraTime);
  1003.           else
  1004.            max_time = 99999999;
  1005.           if (et >= max_time)
  1006.            {
  1007.             if (flag.threat)
  1008.               depth= DOCHECK && (ply+depth<DepthBeyond-DEPTHMARGIN) ?
  1009.                 depth+1: depth;
  1010.             else
  1011.               depth= (depth < 2) ? 2 : depth;
  1012.            }
  1013.           else
  1014.            depth++;
  1015. #else // this is the Kong Sian way, always extend check search
  1016.       // this way costs more time but may be better
  1017.           depth++;
  1018. #endif
  1019.       }
  1020.       else if ((ply>1 && PawnThreat[ply - 1] && ply+depth<DepthBeyond-DEPTHMARGIN) ||
  1021.                (flag.rcptr && ply>2 && CptrFlag[ply - 1] && CptrFlag[ply - 2] &&
  1022.                ((ply<Sdepth+2 && CptrFlag[ply-1]==CptrFlag[ply-2]) ||
  1023. // the next line is a fix from Kong Sian, old way may be better
  1024.             (score > root->score - valueP/4 && score < root->score + valueP/4))) // FIX by Kong SIAN
  1025. //               (score > alpha && score < beta))) // OLD 4PL68 way
  1026.                )
  1027.           ++depth;
  1028.     }
  1029.   else
  1030.     { 
  1031.       int tripple_check = 0;
  1032.       if (score >= alpha &&
  1033.           (InChk || (ply>1 && PawnThreat[ply - 1] && depth<DepthBeyond-4)
  1034.           || (hung[side] > 1 /*&& !ext*/))) { // fix from Kong Sian
  1035.         threat2= 1;
  1036.         ext++;
  1037.         depth= 1;
  1038.       }
  1039.       else if (score <= beta &&
  1040.                ((ply<Sdepth+4 && ply>4 &&
  1041.                 ChkFlag[ply-2] && ChkFlag[ply-4] &&
  1042.                 (ChkFlag[ply-2] != ChkFlag[ply-4] ||
  1043.                 (flag.threat && DOTHREAT && QueenCheck[ply-2])))
  1044.           ||
  1045.                 (flag.threat && ply<DepthBeyond-DEPTHMARGIN && ply>6
  1046.                 && ChkFlag[ply-2] && ChkFlag[ply-4] && ChkFlag[ply-6]
  1047.                 &&  (tripple_check=1)
  1048.                 && ((ply < Sdepth+4 ?
  1049.                   (ChkFlag[ply-2] != ChkFlag[ply-4] || ChkFlag[ply-2] !=
  1050. ChkFlag [ply-6])
  1051.                   : (ChkFlag[ply-2] != ChkFlag[ply-4] &&
  1052.                      ChkFlag[ply-2] != ChkFlag[ply-6] &&
  1053.                      ChkFlag[ply-4] != ChkFlag[ply-6]))
  1054.                 || (DOTHREAT && QueenCheck[ply-2]
  1055.                 && QueenCheck[ply-4] && QueenCheck[ply-6]
  1056.                 && QueenCheck[ply-2] != QueenCheck[ply-6]))
  1057.                 ))) {
  1058.           if (tripple_check && DepthBeyond < Sdepth+13+DEPTHMARGIN)
  1059.             {
  1060.               extdb += 2;
  1061.               DepthBeyond += 2;
  1062.             }
  1063.           depth= 1;
  1064.           ext++;
  1065.           Threat[ply]= threat= 1;
  1066.         }
  1067.     }    
  1068.   ThreatSave[ply]= ((ply>1 && ThreatSave[ply-1]) || threat);
  1069. #endif
  1070.   /*******************************************************************************************/
  1071.   /* try the local transition table if it's there */
  1072.   if (ply>1) TrPnt[ply+1]= TrPnt[ply]; // TMP!! My Fix for move gen
  1073.  
  1074.   /*
  1075.    * if more then DepthBeyond ply past goal depth or at goal depth and
  1076.    * score > beta quit - means we are out of the window
  1077.    */
  1078.   if (ply > DepthBeyond || (depth < 1 && score > beta))
  1079.     {
  1080.       return (score);
  1081.     }
  1082. #if defined ttblsz
  1083.       if ( flag.hash && ply > 1) // fix from Kong Sian
  1084.         {
  1085.         if (ProbeTTable (side, depth, ply, &alpha, &beta, &score) == true)
  1086.           {
  1087.               if (beta == -20000 || alpha > beta)
  1088.             {
  1089.                 bstline[ply] = PV;
  1090.                 bstline[ply + 1] = 0;
  1091.                             /*
  1092.                              * make sure the move is in the
  1093.                              * MoveList
  1094.                              */
  1095.                             if (ply == 1)
  1096.                               {   
  1097.                                   struct leaf tmp;
  1098.                   register int spnt;
  1099.                                   for (spnt = TrPnt[ply]; spnt < TrPnt[ply + 1]; spnt++)
  1100.                                     {
  1101.                                         if (((Tree[spnt].f << 8) | Tree[spnt].t) == PV)
  1102.                                           {
  1103.                                               if (ply == 1 && Tree[spnt].score == DONTUSE) {bstline[1] = 0; break;}
  1104.                                               Tree[spnt].score = (beta == -20000) ? score : alpha;
  1105.                                               if (abs (score) > 9000) Tree[spnt].flags |= exact;
  1106.                                               if (spnt != TrPnt[ply])
  1107.                                                 {
  1108.                                                     tmp = Tree[TrPnt[ply]];
  1109.                                                     Tree[TrPnt[ply]] = Tree[spnt];
  1110.                                                     Tree[spnt] = tmp;
  1111.                                                 }
  1112. #include "debug64.h"
  1113.                                               if (beta == -20000) return (score);
  1114.                                               else return (alpha);
  1115.                                           }
  1116.                                     }
  1117.                               } else {
  1118.                 register int i = TrPnt[ply];
  1119.                 Tree[i].t = PV & 0x3f;
  1120.                 Tree[i].f = PV>>8;
  1121.                 Tree[i].flags = 0;
  1122.                 Tree[i].reply = 0;
  1123.                 Tree[i].score = (beta == -20000) ? score : alpha; 
  1124.                 TrPnt[ply+1] = i+1;
  1125.                                 if (abs (score) > 9000) Tree[i].flags |= exact; 
  1126.                 if (beta == -20000) return (score); 
  1127.                                     else return (alpha); 
  1128.                   }
  1129.  
  1130.             }
  1131.           }
  1132. #ifdef HASHFILE
  1133.         /* ok try the transition file if its there */
  1134.         else if (hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit)
  1135.              && (ProbeFTable (side, depth, ply, &alpha, &beta, &score) == true))
  1136.           {
  1137.               if (beta == -20000 || alpha > beta)
  1138.             {
  1139.                 bstline[ply] = PV;
  1140.                 bstline[ply + 1] = 0;
  1141.                 /*
  1142.                  * make sure the move is in the
  1143.                  * MoveList
  1144.                  */
  1145.                 if (ply == 1)
  1146.                   {
  1147.                   struct leaf tmp;
  1148.                   register int spnt;
  1149.                   for (spnt = TrPnt[ply]; spnt < TrPnt[ply + 1]; spnt++)
  1150.                     {
  1151.                     if (((Tree[spnt].f << 8) | Tree[spnt].t) == PV)
  1152.                       {
  1153.                                 if (ply == 1 && Tree[spnt].score == DONTUSE) {bstline[1] = 0; break;}
  1154.                           Tree[spnt].score = (beta == -20000) ? score : alpha;
  1155.                           if (abs (score) > 9000) Tree[spnt].flags |= exact;
  1156.                           if (spnt != TrPnt[ply])
  1157.                         {
  1158.                             tmp = Tree[TrPnt[ply]];
  1159.                             Tree[TrPnt[ply]] = Tree[spnt];
  1160.                             Tree[spnt] = tmp;
  1161.                         }
  1162.                           PutInTTable (side, score, depth, ply, /*alpha,*/ beta, PV);
  1163. #include "debug10.h"
  1164.                           if (beta == -20000) return (score);
  1165.                           else return (alpha);
  1166.                       }
  1167.                     }
  1168.                    } else {
  1169.                                 register int i = TrPnt[ply];
  1170.                                 Tree[i].t = PV & 0x3f;
  1171.                                 Tree[i].f = PV>>8;
  1172.                                 Tree[i].score = (beta == -20000) ? score : alpha;
  1173.                 TrPnt[ply+1] = i+1;
  1174.                                 if (abs (score) > 9000) Tree[i].flags |= exact;
  1175.                                 if (beta == -20000) return (score);
  1176.                                     else return (alpha);
  1177.                               }
  1178.  
  1179.  
  1180.             }
  1181.           }
  1182. #endif // HASHFILE
  1183.      }
  1184. #endif /* ttblsz */
  1185.       if (depth > 0 || (background && ply < Sdepth + 2)) {if(ply >1)
  1186. #ifdef LEGAL
  1187.         VMoveList (side, ply);}
  1188. #else
  1189.         MoveList (side, ply);}
  1190. #endif
  1191.     else
  1192.       {
  1193. #ifdef LEGAL
  1194.         VCaptureList (side, ply);
  1195. #else
  1196.         CaptureList (side, ply);
  1197. #endif
  1198.     if(!SAVEHT)SAVEHT = ply;
  1199.       }
  1200.  
  1201.  
  1202.  
  1203.   /* no moves return what we have */
  1204.  
  1205.   /*
  1206.    * normally a search will continue til past goal and no more capture
  1207.    * moves exist
  1208.    */
  1209.   /* unless it hits DepthBeyond */
  1210.   if (TrPnt[ply] == TrPnt[ply + 1]) { if(!InChk) return (score); else return (-10001+ply); }
  1211.  
  1212.  
  1213.  
  1214.   /* if not at goal set best = -inf else current score */
  1215.      best = (depth >0) ? -12000:score;
  1216. #ifdef NULLMOVE
  1217.  
  1218.   PVarisave = PVari;
  1219.   if (!null &&                         /* no previous null-move */
  1220.       !PVari &&                        /* no null-move during the PV */
  1221.       (ply > 1) && // was 2 changed by Kong Sian
  1222.       (ply <= Sdepth) &&                       /* not at ply 1 */
  1223.       (depth > 2) && // changed by Kong Sian   /* not during the quienscesearch */
  1224.       !InChk &&                        /* no check */
  1225.       ((mtl[side] + mtl[xside]) > NULLMOVELIM))
  1226.     /* enough material such that zugzwang is unlike but who knows which value
  1227.        is suitable? */
  1228.     {
  1229.       
  1230.       /* ok, we make a null move, i.e.  this means we have nothing to do
  1231.       but we have to keep the some arrays up to date otherwise gnuchess
  1232.       gets confused.  Maybe somebody knows exactly which informations are
  1233.      important and which not.
  1234.  
  1235.      Another idea is that we try the null-move first and generate the
  1236.      moves later.  This may save time but we have to take care that
  1237.      PV and other variables contain the right value so that the move
  1238.      ordering works right.
  1239.      */
  1240.       register struct GameRec *g;
  1241.       
  1242.       nxtline[ply + 1] = 0;
  1243.       CptrFlag[ply] = 0;
  1244.       PawnThreat[ply] = 0;
  1245.       Tscore[ply] = score;
  1246.       PVsave = PV;
  1247.       PV = 0;
  1248.       null = 1;
  1249.       g = &GameList[++GameCnt];
  1250.       g->hashkey = hashkey;
  1251.       g->hashbd = hashbd;
  1252.       epsquare = -1;
  1253.       TOsquare = -1;
  1254.       g->Game50 = Game50;
  1255. #ifdef LONGINTS
  1256.       g->gmove = 0xffffffff;
  1257. #else
  1258.       g->gmove = 0xffff;
  1259. #endif
  1260.       g->flags = 0;
  1261.       g->piece = 0;
  1262.       g->color = neutral;
  1263.       
  1264. //      best = -search (xside, ply + 1, false, depth - 2, -beta - 1, -beta, nxtline, &rcnt,false,false);
  1265. //this next line a fix from Kong Sian replaces above line
  1266.       best = -search (xside, ply + 1, false, depth - 2, -beta, -beta, nxtline, &rcnt,false,false);
  1267.       null = 0;
  1268.       PV = PVsave;
  1269.       GameCnt--;
  1270.       if (best < alpha) best = -12000;
  1271.       else if (best > 0 && best > beta) return (best);
  1272.       else
  1273.      best = -12000;
  1274.     }
  1275. #else 
  1276. #ifdef DEEPNULL
  1277.  
  1278.   /*
  1279.    * The deepnull algoritm is taken from the article by
  1280.    * Christian Donninger in ICCA journal Vol 16, No. 3.  TomV
  1281.    */
  1282.   PVarisave = PVari;
  1283.   if ((myflagdeepnull ? !didnull : !null) &&    /* no previous null-move */
  1284.     //  !flag.nonull &&
  1285.       !no_null &&
  1286.       !PVari &&            /* no null-move during the PV */
  1287.       (ply > (myflagdeepnull ? 1: 2)) &&        /* not at ply 1 */
  1288.       (score > alpha - 150 || !myflagdeepnull) &&
  1289.       (ply <= Sdepth || myflagdeepnull) &&
  1290.       (depth > (myflagdeepnull ? (verydeep ? 1: 2): 3)) &&
  1291.       !InChk &&            /* no check */
  1292.       /* enough material such that zugzwang is unlikely: */
  1293.       ! (emtl[xside] == 0 || emtl[side] <= valueB))
  1294.     {
  1295.  
  1296.       /* ok, we make a null move, i.e.  this means we have nothing to do
  1297.       but we have to keep the some arrays up to date otherwise gnuchess
  1298.       gets confused.
  1299.  
  1300.      Another idea is that we try the null-move first and generate the
  1301.      moves later.  This may save time but we have to take care that
  1302.      PV and other variables contain the right value so that the move
  1303.      ordering works right.
  1304.      */
  1305.       CptrFlag[ply] = 0;
  1306.       PawnThreat[ply] = 0;
  1307.       Tscore[ply] = score;
  1308.       PVsave = PV;
  1309.       PV = 0;
  1310.       epsquare = -1;
  1311.       TOsquare = -1;
  1312.       if (!null)
  1313.         null= ply;
  1314.       if (myflagdeepnull) {
  1315.         int nmscore = -search (xside, ply + 1, (depth >= 3 ? depth - 3: 0), ext, -beta, -alpha, nxtline, &rcnt,false,1);
  1316.         if (ply == null)
  1317.           null = 0;
  1318.         PV = PVsave;
  1319.     if (nmscore > beta) {
  1320.       DepthBeyond-= extdb;
  1321.       return nmscore;
  1322.         }
  1323.     if (nmscore > alpha)
  1324.       best= nmscore;
  1325.         if (depth <= 3 && ply < DepthBeyond-depth-4
  1326.             && score >= beta && nmscore < score - 350)
  1327.               depth++;
  1328.       } else {
  1329. // change to -beta,-beta from K SIAN
  1330.         best = -search (xside, ply + 1, depth - 2, ext, -beta - 1, -beta, nxtline, &rcnt, false, 1);
  1331. //        best = -search (xside, ply + 1, depth - 2, ext, -beta, -beta, nxtline, &rcnt, false, 1);
  1332.         null = 0;
  1333.         PV = PVsave;
  1334.         if (best < alpha) best = -12000;
  1335.         else if (best > beta) {
  1336.        DepthBeyond-= extdb;
  1337.            return (best);
  1338.         }  else best = -12000;
  1339.       }
  1340.     }
  1341. #endif //deepnull
  1342. #endif // nullmove
  1343.   /* if best so far is better than alpha set alpha to best */
  1344.     if(best>alpha)alpha=best;
  1345.   /********************** main loop ************************************************************************/
  1346.   /* look at each move until no more or beta cutoff */
  1347.    do_pvs = 0;
  1348. //   for (pnt = pbst = TrPnt[ply]; pnt < TrPnt[ply + 1] &&
  1349. //    (best <= beta || (ply == 1 && best > 9000)); pnt++) /* Find best mate, TomV TMP!!*/
  1350.   for (pnt = pbst = TrPnt[ply]; pnt < TrPnt[ply + 1] && best <= beta; pnt++)
  1351.     {
  1352.       /* find the most interesting looking of the remaining moves */
  1353.       if (ply > 1)
  1354.     pick (pnt, TrPnt[ply + 1] - 1);
  1355. #if defined NULLMOVE || defined DEEPNULL
  1356.       PVari = PVarisave && (pnt == pbst/*TrPnt[ply]*/);  /* Is this the PV? */
  1357. #endif
  1358.  
  1359.       node = &Tree[pnt];
  1360.       /* is this a forbidden move */
  1361.       if (pnt == pbst)
  1362.        do_pvs = myflagpvs && PVari; // this line a fix from Kong Sian, replaced line below
  1363. //        do_pvs= myflagpvs && !null && (PrVar[ply] == ((node->f << 8) | node->t));
  1364.       if (ply == 1 && node->score == DONTUSE)
  1365.     continue;
  1366. #ifdef DEBUG
  1367.     if(debuglevel & (512 | 1024)){
  1368.         if(!tracen)traceflag = ((ply >traceply)?false:true);
  1369.          else
  1370.         if(ply <= tracen && (ply ==1 || traceflag))
  1371.             { 
  1372.             if(trace[ply] == (Tree[pnt].t |(Tree[pnt].f<<8))) traceflag = true; else traceflag = false; }
  1373.         tracelog[ply] = (Tree[pnt].t |(Tree[pnt].f<<8));
  1374.         tracelog[ply+1] = 0;
  1375. }
  1376. #endif
  1377.       nxtline[ply + 1] = 0;
  1378.  
  1379. #if !defined CHESSTOOL && !defined XBOARD
  1380.       /* if at top level */
  1381.       if (ply == 1)
  1382.     {            /* at the top update search status */
  1383.       if (flag.post)
  1384. #ifdef QUIETBACKGROUND
  1385.         if (!background)
  1386. #endif /* QUIETBACKGROUND */
  1387.           ShowCurrentMove (pnt, node->f, node->t);
  1388.     }
  1389. #endif
  1390.       /* make the move and go deeper */
  1391.       MakeMove (side, node, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  1392. // FIX from Kong Sian for cpt flag
  1393. //      CptrFlag[ply] = (node->flags & capture); // OLD way
  1394.       CptrFlag[ply] = (node->flags & capture ? TOsquare+1 : 0); // K. Sian way
  1395.       PawnThreat[ply] = (node->flags & pwnthrt);
  1396.       Tscore[ply] = node->score;
  1397.       PV = node->reply;
  1398. #ifdef DEBUG
  1399.       xxxtmp = node->score;
  1400.       tracetmp = traceflag;
  1401. #endif
  1402.       if (do_pvs) {
  1403.             if (pbst == pnt) {
  1404.               node->score= -search (xside, ply + 1,
  1405.                                  depth > 0 ? depth - 1 : 0, ext,
  1406.                                  -beta, -alpha,
  1407.                                  nxtline, &rcnt,SAVEHT, 0);
  1408.             } else {
  1409.               node->score= -search(xside, ply + 1,
  1410.                               depth > 0 ? depth - 1 : 0, ext,
  1411.                               -alpha-1, -alpha,
  1412. // below line is a fix from Kong Sian, replaces above line
  1413. //                              -alpha, -alpha,
  1414.                               nxtline, &rcnt,SAVEHT, 0);
  1415. // next if stmt improved by Kong Sian after 4pl68
  1416.               if (/*node->score >= best && */alpha <= node->score
  1417.               /*&& node->score <= beta*/)
  1418.                   node->score = -search (xside, ply + 1,
  1419.                                  depth > 0 ? depth - 1 : 0, ext,
  1420.                                  -beta, /*-node->score*/-alpha,
  1421.                                  nxtline, &rcnt,SAVEHT, 0);
  1422.             }
  1423.           } else
  1424.  
  1425.       node->score = -search (xside, ply + 1,
  1426.                  (depth > 0) ? depth - 1 : 0, ext,
  1427.                  -beta, -alpha,
  1428.                  nxtline, &rcnt, SAVEHT, false);
  1429.       node->width = (ply % 2 == 1) ? (TrPnt[ply + 2] - TrPnt[ply + 1]) : 0;
  1430.       if (abs (node->score) > 9000) node->flags |= exact;
  1431.           else if (rcnt == 1) node->score = 0;
  1432.       if(node->score == (9999-ply) && !ChkFlag[ply] ) {node->flags |= draw;
  1433.           node->score = (-contempt);}
  1434. #include "debug256.h"
  1435.       if ((rcnt >= 2 || GameCnt - Game50 > 99 
  1436. /*|| (node->score == 9999 - ply && !ChkFlag[ply])*/
  1437.           ))
  1438.         {
  1439.           node->flags |= (draw | exact);
  1440.           DRAW = CP[58];    /* Draw */
  1441.           node->score = -contempt;
  1442.         }
  1443.       node->reply = nxtline[ply + 1];
  1444.       /* reset to try next move */
  1445.       UnmakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
  1446.       /* if best move so far */
  1447.       if (!flag.timeout && ((node->score > best) || ((node->score == best) && (node->width > bestwidth))))
  1448.     {
  1449.       /*
  1450.        * all things being equal pick the denser part of the
  1451.        * tree
  1452.        */
  1453.       bestwidth = node->width;
  1454.  
  1455.       /*
  1456.        * if not at goal depth and better than alpha and not
  1457.        * an exact score increment by depth
  1458.        */
  1459.       if (depth > 0 && node->score > alpha && !(node->flags & exact))
  1460.         node->score += depth;
  1461.       best = node->score;
  1462.       pbst = pnt;
  1463.       if (best > alpha) { alpha = best; }
  1464.       /* update best line */
  1465.       for (j = ply + 1; nxtline[j] > 0; j++) bstline[j] = nxtline[j];
  1466.       bstline[j] = 0;
  1467.       bstline[ply] = (node->f << 8) | node->t;
  1468.       /* if at the top */
  1469.       if (ply == 1)
  1470.         {
  1471.           /*
  1472.            * if its better than the root score make it
  1473.            * the root
  1474.            */
  1475. // next line has || pnt > 0 added in pl71
  1476.           if ((best > root->score) || ((best == root->score) && (bestwidth > 
  1477.               root->width)) || pnt > 0)
  1478.         {
  1479.           tmp = Tree[pnt];
  1480.           for (j = pnt - 1; j >= 0; j--) Tree[j + 1] = Tree[j];
  1481.           Tree[0] = tmp;
  1482.           pbst = 0;
  1483.         }
  1484.               if (Sdepth > 2)
  1485.                global_tmp_score = best;
  1486. #if !defined CHESSTOOL && !defined XBOARD
  1487. #ifdef QUIETBACKGROUND
  1488.           if (!background)
  1489. #endif /* QUIETBACKGROUND */
  1490.         if (Sdepth > 2)
  1491.           if (best > beta)
  1492.             {
  1493.               ShowResults (best, bstline, '+');
  1494. #ifdef DEBUG41
  1495.               debug41 (best, bstline, '+');
  1496. #endif
  1497.             }
  1498.           else if (best < alpha)
  1499.             {
  1500.               ShowResults (best, bstline, '-');
  1501. #ifdef DEBUG41
  1502.               debug41 (best, bstline, '-');
  1503. #endif
  1504.             }
  1505.           else
  1506.                    {
  1507.             ShowResults (best, bstline, '&');
  1508.                    }
  1509. #ifdef DEBUG41
  1510.           debug41 (best, bstline, '&');
  1511. #endif
  1512. #else
  1513.        if ((!background) && (Sdepth >2) && (best < alpha)){
  1514.             TCcount = 0;
  1515.         ExtraTime += 20*TCleft;
  1516.        }
  1517. #endif
  1518.         }
  1519.     }
  1520.       if (flag.timeout)
  1521.     {
  1522.           DepthBeyond-= extdb;
  1523. #if defined NULLMOVE || defined DEEPNULL
  1524.   PVari = PVarisave;
  1525. #endif
  1526.       return (Tscore[ply - 1]);
  1527.     }
  1528.     }
  1529.  
  1530.   /******************************************************************************************/
  1531. // this best == -10000 line added in 4pl71
  1532.   if (best == -10000+ply) bstline[ply] = 0;
  1533.   node = &Tree[pbst];
  1534.   mv = (node->f << 8) | node->t;
  1535. #if defined NULLMOVE || defined DEEPNULL
  1536.   PVari = PVarisave;
  1537. #endif
  1538. #ifdef DEBUG
  1539. #include "debug512.h"
  1540. #endif
  1541.  
  1542.   /*
  1543.    * we have a move so put it in local table - if it's already there
  1544.    * done else if not there or needs to be updated also put it in
  1545.    * hashfile
  1546.    */
  1547. #if ttblsz
  1548.   if (flag.hash && !SAVEHT  /*&& ply <= Sdepth*/ && *rpt == 0 && best == alpha)
  1549.     {
  1550.       PutInTTable (side, best, depth, SAVEHT?SAVEHT:ply, /*alpha,*/ beta, mv);
  1551.     }
  1552. #endif /* ttblsz */
  1553.  
  1554.   if (depth > 0)
  1555.     {
  1556. #ifdef HISTORY
  1557.       j = (node->f << 8) | node->t; // was 6 should be 8
  1558.       if (side == black)
  1559.     j |= 0x4000;
  1560. // BELOW IS NEWEST WAY TO UPDATE HISTORY TABLE, AFTER 4PL69
  1561. #ifndef CLEARHISTBETWEENMOVES
  1562.       if (history[j] < HISTORYLIM)
  1563.         history[j] |= (unsigned short) 1 << depth;
  1564. #else
  1565. // below is original way
  1566.       if (history[j] < HISTORYLIM)
  1567.     history[j] |= (unsigned short) 1<<depth;
  1568. // here is a Kong Sian fix from after 4pl68
  1569. //      if (history[j] < ((unsigned short) 1 << depth))
  1570. //        history[j] = ((unsigned short) 1 << depth);
  1571. #endif
  1572.  
  1573. #endif
  1574.       if (node->t != (short)(GameList[GameCnt].gmove & 0xFF))
  1575.     if (best <= beta)
  1576.       killr3[ply] = mv;
  1577.     else if (mv != killr1[ply])
  1578.       {
  1579.         killr2[ply] = killr1[ply];
  1580.         killr1[ply] = mv;
  1581.       }
  1582.       killr0[ply] = ((best > 9000) ? mv : 0);
  1583.     }
  1584.  
  1585.   DepthBeyond -= extdb; // this LINE added after 4pl68 by Kong Sian
  1586.  
  1587.   return (best);
  1588. }
  1589.  
  1590.  
  1591.  
  1592. int
  1593. castle (short side, short kf, short kt, short iop)
  1594.  
  1595. /* Make or Unmake a castling move. */
  1596.  
  1597. {
  1598.   register short rf, rt, t0, xside;
  1599.  
  1600.   xside = side ^ 1;
  1601.   if (kt > kf)
  1602.     {
  1603.       rf = kf + 3;
  1604.       rt = kt - 1;
  1605.     }
  1606.   else
  1607.     {
  1608.       rf = kf - 4;
  1609.       rt = kt + 1;
  1610.     }
  1611.   if (iop == 0)
  1612.     {
  1613.       if (kf != kingP[side] ||
  1614.       board[kf] != king ||
  1615.       board[rf] != rook ||
  1616.       color[kf] != side ||
  1617.       color[rf] != side ||
  1618.       Mvboard[kf] != 0 ||
  1619.       Mvboard[rf] != 0 ||
  1620.       color[kt] != neutral ||
  1621.       color[rt] != neutral ||
  1622.       color[kt - 1] != neutral ||
  1623.       SqAtakd3 (kf, xside) ||
  1624.       SqAtakd3 (kt, xside) ||
  1625.       SqAtakd3 (rt, xside))
  1626.     return (false);
  1627.     }
  1628.   else
  1629.     {
  1630.       if (iop == 1)
  1631.     {
  1632.           Castled[side] = 1;
  1633.       castld[side] = true;
  1634.       Mvboard[kf]++;
  1635.       Mvboard[rf]++;
  1636.     }
  1637.       else
  1638.     {
  1639.           Castled[side] = 0;
  1640.       castld[side] = false;
  1641.       Mvboard[kf]--;
  1642.       Mvboard[rf]--;
  1643.       t0 = kt;
  1644.       kt = kf;
  1645.       kf = t0;
  1646.       t0 = rt;
  1647.       rt = rf;
  1648.       rf = t0;
  1649.     }
  1650.       board[kt] = king;
  1651.       color[rt] = color[kt] = side;
  1652.       Pindex[kt] = 0;
  1653.       board[kf] = no_piece;
  1654.       color[rf] = color[kf] = neutral;
  1655.       board[rt] = rook;
  1656.       Pindex[rt] = Pindex[rf];
  1657.       board[rf] = no_piece;
  1658.       PieceList[side][Pindex[kt]] = kt;
  1659.       PieceList[side][Pindex[rt]] = rt;
  1660.       UpdateHashbd (side, king, kf, kt);
  1661.       UpdateHashbd (side, rook, rf, rt);
  1662.     }
  1663.   return (true);
  1664. }
  1665.  
  1666.  
  1667. void
  1668. EnPassant (short xside, short f, short t, short iop)
  1669.  
  1670. /*
  1671.  * Make or unmake an en passant move.
  1672.  */
  1673.  
  1674. {
  1675.   register short l;
  1676.  
  1677.   l = t + ((t > f) ? -8 : 8);
  1678.   if (iop == 1)
  1679.     {
  1680.       myEnPassant[xside] = 1;
  1681.       board[l] = no_piece;
  1682.       color[l] = neutral;
  1683.     }
  1684.   else
  1685.     {
  1686.       myEnPassant[xside] = 0;
  1687.       board[l] = pawn;
  1688.       color[l] = xside;
  1689.     }
  1690.   InitializeStats ();
  1691. }
  1692.  
  1693. void
  1694. UpdatePieceList (SHORT side, SHORT sq, SHORT iop,short piece)
  1695.  
  1696. /*
  1697.  * Update the PieceList and Pindex arrays when a piece is captured or when a
  1698.  * capture is unmade.
  1699.  */
  1700.  
  1701. {
  1702.   register SHORT i;
  1703.  
  1704.  if( iop == 1 ) {
  1705.    i = Pindex[ sq ];
  1706.    if( i < PieceCnt[ side ] ) {
  1707.      PieceList[ side ][ i ] = PieceList[ side ][ PieceCnt[ side ] ];
  1708.      Pindex[ PieceList[ side ][ i ] ] = i;
  1709.    }
  1710.    PieceCnt[ side ]--;    
  1711.  }
  1712.   else
  1713.     { if(piece != king){
  1714.       PieceCnt[side]++;
  1715.       PieceList[side][PieceCnt[side]] = sq;
  1716.       Pindex[sq] = PieceCnt[side];
  1717.       } else {
  1718.     PieceCnt[side]++;
  1719.           for (i = PieceCnt[side]; i > 0; i--)
  1720.             {
  1721.               PieceList[side][i] = PieceList[side][i - 1];
  1722.               Pindex[PieceList[side][i]] = i;
  1723.             } 
  1724.         PieceList[side][0] = sq;
  1725.         Pindex[sq] = 0;
  1726.  
  1727.       }
  1728.     }
  1729. }
  1730.  
  1731. void
  1732. MakeMove (SHORT side,
  1733.       struct leaf *node,
  1734.       SHORT *tempb,    /* color of to square */
  1735.       SHORT *tempc,    /* piece at to square */
  1736.       SHORT *tempsf,    /* static value of piece on from */
  1737.       SHORT *tempst,    /* static value of piece on to */
  1738.       SHORT *INCscore)    /* score increment for pawn structure change */
  1739.  
  1740. /*
  1741.  * Update Arrays board[], color[], and Pindex[] to reflect the new board
  1742.  * position obtained after making the move pointed to by node. Also update
  1743.  * miscellaneous stuff that changes when a move is made.
  1744.  */
  1745.  
  1746. {
  1747.   register SHORT f, t, xside, ct, cf;
  1748.   register struct GameRec *g;
  1749.  
  1750.   xside = side ^ 1;
  1751.   g = &GameList[++GameCnt];
  1752.   g->hashkey = hashkey;
  1753.   g->hashbd = hashbd;
  1754.   g->epssq = epsquare;
  1755.   f = node->f;
  1756.   t = node->t;
  1757.   epsquare = -1;
  1758.   /* FROMsquare = f;*/
  1759.   TOsquare = t;
  1760.   *INCscore = 0;
  1761.   g->Game50 = Game50;
  1762.   g->gmove = (f << 8) | t;
  1763.   g->flags = node->flags;
  1764.   if (node->flags & cstlmask)
  1765.     {
  1766.       g->piece = no_piece;
  1767.       g->color = side;
  1768.       (void) castle (side, f, t, 1);
  1769.       Game50 = GameCnt;
  1770.     }
  1771.   else
  1772.     {
  1773.       if (!(node->flags & capture) && (board[f] != pawn))
  1774.     { IncrementRPThash(side,hashkey); }
  1775.       else
  1776.     Game50 = GameCnt;
  1777.       *tempsf = svalue[f];
  1778.       *tempst = svalue[t];
  1779.       g->piece = *tempb = board[t];
  1780.       g->color = *tempc = color[t];
  1781.       if (*tempc != neutral)
  1782.     {
  1783.       UpdatePieceList (*tempc, t, 1,*tempb);
  1784.       /* if capture decrement pawn count */
  1785.       if (*tempb == pawn)
  1786.         {
  1787.           --PawnCnt[*tempc][column (t)];
  1788.         }
  1789.       if (board[f] == pawn)
  1790.         {
  1791.           cf = column (f);
  1792.           ct = column (t);
  1793.           /* move count from from to to */
  1794.           --PawnCnt[side][cf];
  1795.           ++PawnCnt[side][ct];
  1796.  
  1797.           /*
  1798.            * calculate increment for pawn structure
  1799.            * changes
  1800.            */
  1801.           /* doubled or more - */
  1802.           if (PawnCnt[side][ct] > (1 + PawnCnt[side][cf]))
  1803.         *INCscore -= 15;
  1804.           /* went to empty column + */
  1805.           else if (PawnCnt[side][ct] < 1 + PawnCnt[side][cf])
  1806.         *INCscore += 15;
  1807.  
  1808.           /*
  1809.            * went to outside col or empty col on one
  1810.            * side ????????
  1811.            */
  1812.           else if (ct == 0 || ct == 7 || PawnCnt[side][ct + ct - cf] == 0)
  1813.         *INCscore -= 15;
  1814.         }
  1815.       mtl[xside] -= value[*tempb];
  1816.       if (*tempb == pawn)
  1817.         pmtl[xside] -= valueP;
  1818.       UpdateHashbd (xside, *tempb, -1, t);
  1819.       *INCscore += *tempst;
  1820.       Mvboard[t]++;
  1821.     }
  1822.       color[t] = color[f];
  1823.       board[t] = board[f];
  1824.       svalue[t] = svalue[f];
  1825.       Pindex[t] = Pindex[f];
  1826.       PieceList[side][Pindex[t]] = t;
  1827.       color[f] = neutral;
  1828.       board[f] = no_piece;
  1829.       if (board[t] == pawn)
  1830.     if (t - f == 16)
  1831.       epsquare = f + 8;
  1832.     else if (f - t == 16)
  1833.       epsquare = f - 8;
  1834.       if (node->flags & promote)
  1835.     {
  1836.       board[t] = node->flags & pmask;
  1837.       if (board[t] == queen)
  1838.         HasQueen[side]++;
  1839.       else if (board[t] == rook)
  1840.         HasRook[side]++;
  1841.       else if (board[t] == bishop)
  1842.         HasBishop[side]++;
  1843.       else if (board[t] == knight)
  1844.         HasKnight[side]++;
  1845.       --PawnCnt[side][column (t)];
  1846.       mtl[side] += value[board[t]] - valueP;
  1847.       pmtl[side] -= valueP;
  1848.       UpdateHashbd (side, pawn, f, -1);
  1849.       UpdateHashbd (side, board[t], f, -1);
  1850.       *INCscore -= *tempsf;
  1851.     }
  1852.       if (node->flags & epmask)
  1853.     EnPassant (xside, f, t, 1);
  1854.       else
  1855.     UpdateHashbd (side, board[t], f, t);
  1856.       Mvboard[f]++;
  1857.     }
  1858. }
  1859.  
  1860. void
  1861. UnmakeMove (SHORT side,
  1862.         struct leaf *node,
  1863.         SHORT *tempb, /* -> piece */
  1864.         SHORT *tempc, /* -> side */
  1865.         SHORT *tempsf,
  1866.         SHORT *tempst)
  1867.  
  1868. /*
  1869.  * Take back a move.
  1870.  */
  1871.  
  1872. {
  1873.   register SHORT f, t, xside;
  1874.  
  1875.   xside = side ^ 1;
  1876.   f = node->f;
  1877.   t = node->t;
  1878.   Game50 = GameList[GameCnt].Game50;
  1879.   if (node->flags & cstlmask)
  1880.     (void) castle (side, f, t, 2);
  1881.   else
  1882.     {
  1883.       color[f] = color[t];
  1884.       board[f] = board[t];
  1885.       svalue[f] = *tempsf;
  1886.       Pindex[f] = Pindex[t];
  1887.       PieceList[side][Pindex[f]] = f;
  1888.       color[t] = *tempc;
  1889.       board[t] = *tempb;
  1890.       svalue[t] = *tempst;
  1891.       if (node->flags & promote)
  1892.     {
  1893.       board[f] = pawn;
  1894.       ++PawnCnt[side][column (t)];
  1895.       mtl[side] += valueP - value[node->flags & pmask];
  1896.       pmtl[side] += valueP;
  1897.       UpdateHashbd (side, (SHORT) node->flags & pmask, -1, t);
  1898.       UpdateHashbd (side, pawn, -1, t);
  1899.     }
  1900.       if (*tempc != neutral)
  1901.     {
  1902.       UpdatePieceList (*tempc, t, 2,*tempb);
  1903.       if (*tempb == pawn)
  1904.         {
  1905.           ++PawnCnt[*tempc][column (t)];
  1906.         }
  1907.       if (board[f] == pawn)
  1908.         {
  1909.           --PawnCnt[side][column (t)];
  1910.           ++PawnCnt[side][column (f)];
  1911.         }
  1912.       mtl[xside] += value[*tempb];
  1913.       if (*tempb == pawn)
  1914.         pmtl[xside] += valueP;
  1915.       UpdateHashbd (xside, *tempb, -1, t);
  1916.       Mvboard[t]--;
  1917.     }
  1918.       if (node->flags & epmask)
  1919.     {
  1920.       EnPassant (xside, f, t, 2);
  1921.     }
  1922.       else
  1923.     UpdateHashbd (side, board[f], f, t);
  1924.       Mvboard[f]--;
  1925.       if (!(node->flags & capture) && (board[f] != pawn))
  1926.     { DecrementRPThash(side,hashkey); }
  1927.     }
  1928.   epsquare = GameList[GameCnt--].epssq;
  1929. }
  1930.  
  1931.  
  1932. void
  1933. InitializeStats (void)
  1934.  
  1935. /*
  1936.  * Scan thru the board seeing what's on each square. If a piece is found,
  1937.  * update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
  1938.  * determine the material for each side and set the hashkey and hashbd
  1939.  * variables to represent the current board position. Array
  1940.  * PieceList[side][indx] contains the location of all the pieces of either
  1941.  * side. Array Pindex[sq] contains the indx into PieceList for a given
  1942.  * square.
  1943.  */
  1944.  
  1945. {
  1946.   register SHORT i, sq;
  1947.  
  1948.   epsquare = -1;
  1949.   for (i = 0; i < 8; i++)
  1950.     {
  1951.       PawnCnt[white][i] = PawnCnt[black][i] = 0;
  1952.     }
  1953.   mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
  1954.   PieceCnt[white] = PieceCnt[black] = 0;
  1955.   hashbd = hashkey = 0;
  1956.   for (sq = 0; sq < 64; sq++)
  1957.     if (color[sq] != neutral)
  1958.       {
  1959.     mtl[color[sq]] += value[board[sq]];
  1960.     if (board[sq] == pawn)
  1961.       {
  1962.         pmtl[color[sq]] += valueP;
  1963.         ++PawnCnt[color[sq]][column (sq)];
  1964.       }
  1965.     Pindex[sq] = ((board[sq] == king) ? 0 : ++PieceCnt[color[sq]]);
  1966.  
  1967.     PieceList[color[sq]][Pindex[sq]] = sq;
  1968.     UpdateHashbd(color[sq], board[sq], -1, sq);
  1969.       }
  1970. }
  1971.